#include <iostream>

#include "Logger.h"

// 先定义再给全局变量赋值
namespace Logger
{
    void defaultOutputFunc(const char *log, int len)
    {
        ::fwrite(log, len, sizeof(char), stdout);
    }

    void defaultFlushFunc()
    {
        ::fflush(stdout);
    }
}

// 桥接：用户 - 全局变量 - 日志
Logger::Logger::OutputFunc gOutputFunc = Logger::defaultOutputFunc;
Logger::Logger::FlushFunc gFlushFunc = Logger::defaultFlushFunc;
Logger::Logger::LogLevel gLogLevel = Logger::Logger::LogLevel::INFO;

namespace Logger
{
    Logger::Logger(LogLevel logLevel, const char *fileName, int lineNum)
        : impl_(logLevel, fileName, lineNum)
    {
    }

    Logger::~Logger()
    {
        this->impl_.stream_ << std::endl; // 每条日志自动换行

        // Logger LoggerImpl -> LogTemplate LogStream -> LogBuffer
        const LogStream::Buffer &buffer = this->impl_.stream_.getBuffer();
        gOutputFunc(buffer.getData(), buffer.getLen()); // 输出

        // 日志级别FATAL，立即刷新，终止程序
        if (this->impl_.logLevel_ == LogLevel::FATAL)
        {
            gFlushFunc();
            ::abort();
        }
    }

    void Logger::setOutputFunc(const OutputFunc &outputFunc)
    {
        gOutputFunc = outputFunc;
    }

    void Logger::setFlushFunc(const FlushFunc &flushFunc)
    {
        gFlushFunc = flushFunc;
    }

    Logger::Impl::Impl(LogLevel logLevel, const char *fileName, int lineNum)
        : timestamp_(Timestamp::now()),
          logLevel_(logLevel),
          fileName_(fileName),
          lineNum_(lineNum),
          stream_()
    {
        // 时间 级别 文件名 行数 内容（Logger()析构时再写入）
        // 2025-07-11 09:30:16 | INFO  | testLogger.cpp:29 - Hello, 0 abc...xyz
        this->formatTimestamp();
        this->stream_ << " | ";

        const char *logLevelName = this->toLogLevelName(this->logLevel_);
        this->stream_ << LogTemplate(logLevelName, ::strlen(logLevelName));
        this->stream_ << " | ";

        this->fileName_ = this->parseFileName();
        this->stream_ << LogTemplate(this->fileName_, ::strlen(this->fileName_))
                      << ":" << this->lineNum_;
        this->stream_ << " - ";
    }

    thread_local char Logger::Impl::sThreadTimestamp[64]{};
    thread_local time_t Logger::Impl::sThreadlastSeconds{};

    void Logger::Impl::formatTimestamp()
    {
        time_t seconds = static_cast<time_t>(this->timestamp_.getMicroSecondsSinceEpoch() / Timestamp::sMicroSecondsPerSecond);
        int microseconds = static_cast<int>(this->timestamp_.getMicroSecondsSinceEpoch() % Timestamp::sMicroSecondsPerSecond);

        struct tm tmSeconds{};
        // struct tm *tm1 = localtime(&seconds);
        ::localtime_r(&seconds, &tmSeconds); // 依据本地时间转换的线程安全版本

        char secondsBuf[64]{};
        // ::snprintf(secondsBuf, sizeof(secondsBuf), "%4d/%02d/%02d %02d:%02d:%02d",
        //            tmSeconds.tm_year + 1900,
        //            tmSeconds.tm_mon + 1,
        //            tmSeconds.tm_mday,
        //            tmSeconds.tm_hour,
        //            tmSeconds.tm_min,
        //            tmSeconds.tm_sec);
        // ::strftime(secondsBuf, sizeof(secondsBuf), "%Y-%m-%d %H:%M:%S", &tmSeconds);
        ::strftime(Logger::Impl::sThreadTimestamp, sizeof(Logger::Impl::sThreadTimestamp), "%Y-%m-%d %H:%M:%S", &tmSeconds); // 写入线程局部
        Logger::Impl::sThreadlastSeconds = seconds;

        // char microsecondsBuf[64]{};
        // ::snprintf(microsecondsBuf, sizeof(microsecondsBuf), "%06d", microseconds); // 微秒可以是无关紧要，直接写缓冲

        this->stream_ << LogTemplate(Logger::Impl::sThreadTimestamp, ::strlen(Logger::Impl::sThreadTimestamp));
        // << LogTemplate(microsecondsBuf, ::strlen(microsecondsBuf)) << " ";
    }

    const char *Logger::Impl::toLogLevelName(LogLevel logLevel)
    {
        if (logLevel == LogLevel::DEBUG)
        {
            return "DEBUG";
        }
        else if (logLevel == LogLevel::INFO)
        {
            return "INFO "; // 和五个字符的对齐
        }
        else if (logLevel == LogLevel::WARN)
        {
            return "WARN ";
        }
        else if (logLevel == LogLevel::ERROR)
        {
            return "ERROR";
        }
        else if (logLevel == LogLevel::FATAL)
        {
            return "FATAL";
        }
        else // 不会到这
        {
            return "UNKNOWN";
        }
    }

    const char *Logger::Impl::parseFileName()
    {
        const char *slash = ::strrchr(this->fileName_, '/');
        if (slash)
        {
            return slash + 1;
        }
        else
        {
            return this->fileName_;
        }
    }

    void Logger::setLogLevel(Logger::LogLevel logLevel)
    {
        gLogLevel = logLevel;
    }

    Logger::LogLevel Logger::getLogLevel()
    {
        return gLogLevel;
    }
}